/*
 * Copyright 2002-2016 the atnoce.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.atnoce.onepass.core;

import com.atnoce.onepass.utils.Base64;
import com.atnoce.onepass.utils.Cache;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * @author atnoce.com
 * @date 2016/11/5
 * @since 1.0.0
 */
public class SecurityController {
    private static SecurityController sc;
    private SecurityController(){}
    public static SecurityController getSecurityInstence(){
        if(sc==null){
            sc=new SecurityController();
            return sc;
        }else{
            return sc;
        }
    }
    public String encryptionMain(String mainPass){
        for(int a=0;a<100;a++){
            mainPass= DigestUtils.sha512Hex(mainPass);
        }
        return mainPass;
    }
    public String getKey(String src){
        String key=DigestUtils.sha512Hex(src);
        return key;
    }

    //校验主密码
    public  boolean checkMainPass(String pass){
        boolean re= StringUtils.equals(encryptionMain(pass), Cache.getOc().getMainPass());
        if(re){
            Cache.setKey(SecurityController.getSecurityInstence().getKey(pass));
        }
        return re;
    }
    /**
     * AES加密
     * @param content
     * @param password
     * @return
     * @throws java.lang.Exception
     */
    public  String AESencrypt(String content, String password) throws Exception{
        return encrypt(content,password);
    }
    private String encrypt(String content,String password)throws Exception{
        byte[] shaByte = sha(password.getBytes());
        byte[] enCodeFormat = Arrays.copyOf(shaByte, 16);
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

        byte[] byteContent = content.getBytes("utf-8");
        cipher.init(1, key);
        byte[] result = cipher.doFinal(byteContent);
        return Base64.encode(result);
    }
    /**
     * AES解密
     * @param content
     * @param password
     * @return
     * @throws java.lang.Exception
     */
    public  String AESdecrypt(String content, String password) throws Exception{
        return decrypt(content,password);
    }
    private String decrypt(String content,String password)throws Exception{
        byte[] shaByte = sha(password.getBytes());
        byte[] enCodeFormat = Arrays.copyOf(shaByte, 16);
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(2, key);
        byte[] result = cipher.doFinal(Base64.decode(content));
        return new String(result, "utf-8");
    }
    private static byte[] sha(byte[] bytes) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA");
        return digest.digest(bytes);
    }
    /**
     * 加密云账号
     * @param account
     * @return
     * @throws Exception
     */
    public String encryptColudAccount(String account,String mainPass) throws Exception{
        for(int i=0;i<5;i++){
            account= encrypt(account,mainPass);
        }
        return account;
    }
    /**
     * 解密云账号
     * @param account
     * @return
     * @throws Exception
     */
    public String decryptColudAccount(String account,String mainPass) throws Exception{
        for(int i=0;i<5;i++){
            account = decrypt(account, mainPass);
        }
        return account;
    }
}
